from collections.abc import Iterable
from collections.abc import Iterator


class Student(object):
    """自定义可迭代类"""

    def __init__(self) -> None:
        self.names = list()

    def add(self, name):
        self.names.append(name)

    def __iter__(self):
        """
        1. 实现iter方法将一个类变成可迭代对象
        2. 必须返回迭代器的对象引用
        """
        return StuIterator(self)


class StuIterator(object):
    """迭代器对象
        该对象必须实现iter、next方法
    """

    def __init__(self, obj):
        self.obj = obj
        # 记录迭代下标
        self.index = 0

    def __iter__(self):
        pass

    def __next__(self):
        if self.index < len(self.obj.names):
            name = self.obj.names[self.index]
            self.index += 1
            return name
        else:
            raise StopIteration  # 抛出异常，for循环处理异常停止迭代


class Classmate(object):
    """定义一个类即是可迭代对象又是迭代器"""

    def __init__(self):
        self.names = list()
        self.index = 0

    def __iter__(self):
        """迭代器、可迭代类必须实现该方法并返回一个迭代器对象"""
        return self  # Classmate自己就是一个迭代器

    def __next__(self):
        """迭代器必须实现该方法"""
        if self.index < len(self.names):
            name = self.names[self.index]
            self.index += 1
            return name
        else:
            raise StopIteration

    def add(self, name):
        self.names.append(name)


def main():
    # 判断一个变量是否可迭代
    print(isinstance([1, 2, 3], Iterable))
    print(isinstance(1, Iterable))

    # 迭代自定义类
    stu = Student()
    stu.add("slx")
    stu.add("mj")
    stu.add("jay")

    print("student是否可以迭代：", isinstance(stu, Iterable))

    # 获取Student的迭代器对象
    stu_iterator = iter(stu)
    # 判断一个对象是否为迭代器
    print("stu_iterator是否是迭代器对象：", isinstance(stu_iterator, Iterator))

    # 调用迭代器对象的next方法
    print(next(stu_iterator))
    # 每次迭代都会调用next方法
    print("----开始迭代stu对象----")
    for s in stu:
        print(s)

    class_mate = Classmate()
    class_mate.add("技术班")
    class_mate.add("运营班")
    class_mate.add("IT班")
    for cls in class_mate:
        print(cls)


if __name__ == '__main__':
    main()
